
import 'dart:convert';
import 'dart:core' as prefix0;
import 'dart:core';
import 'package:baselib/utils/log_util.dart';
import 'package:baselib/utils/sp_util.dart';
import 'package:dio/dio.dart';
import 'package:framelib/config/api_config.dart';
import 'package:framelib/utils/comm_util.dart';
import 'package:framelib/utils/constant_util.dart';
import 'base_api.dart';
import 'baseentity.dart';
import 'errorhandle.dart';
import 'intercept.dart';

/**
 * lx
 * git：https://gitee.com/twopai
 * dio封装，可设置header、baseUrl、拦截器
 */
class DioUtils {

  static final DioUtils _singleton = DioUtils._internal();

  static DioUtils get instance => DioUtils();

  static  String _baseUrl=ApiConfig.BASE_URL;

  factory DioUtils() {
    return _singleton;
  }

  static Dio _dio;

  DioUtils._internal(){
    var options = BaseOptions(
      connectTimeout: Duration(milliseconds: 15000),
      receiveTimeout: Duration(milliseconds: 30000),
      responseType: ResponseType.plain,
      validateStatus: (status){
        // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
        return true;
      },
      baseUrl: _baseUrl,
    );
    _dio = Dio(options);
    /// 打印Log
    _dio.interceptors.add(LoggingInterceptor());
    /// 适配数据
    _dio.interceptors.add(AdapterInterceptor());
    // (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client){
    //   client.badCertificateCallback = (cert, host, port){
    //     return true;
    //   };
    // };
  }
  //初始化dio
  initDio({String baseUrl:''}){
    _baseUrl=baseUrl;
  }

  //添加拦截器
  DioUtils addInterceptor({Interceptor interceptor}){
    if(interceptor!=null)_dio?.interceptors?.add(interceptor);
    return this;
  }
  //切换baseUrl
  DioUtils setBaseUrl({String baseUrl:''}){
    if((baseUrl??'').isEmpty){
      _dio?.options?.baseUrl=_baseUrl;
    }else{
      _dio?.options?.baseUrl=baseUrl??_baseUrl;
    }
    return this;
  }
  //设置 Headers
  DioUtils setHeaders({List<Map<String,dynamic>> headers}){
    if((headers??[]).isNotEmpty){
      headers?.forEach((element) {
        _dio?.options?.headers?.addAll(element);
      });
    }
    return this;
  }

  Options _checkOptions(method,data, Options options,{bool isAuth:false,String contentType}) {
    if (options == null) options = new Options();
    if(options.headers==null){
      options.headers={};
    }
    // if(!(isAuth??false)){}
    options.headers.addAll(
        {
          "Content-Type": contentType??'application/json;charset=UTF-8',
          "loginToken": SpUtil.getString(ConstantUtil.token),
          "sign": CommUtil.toStringKey(data??{"": ""}),
          "language": 'en_us',
          "appId": ApiConfig.wyyx_app_id
        }
    );
    options.method = method;
    return options;
  }





  // 数据返回格式统一，统一处理异常
  Future<BaseEntity<T>> _request<T>(String method, String url, {
    bool isFormData:false,
    bool isAuth:false,
    dynamic data,Map<String, dynamic> queryParameters,String contentType,
      CancelToken cancelToken, Options options,Function generateOBJ}) async {
    FormData formData;
    if(isFormData??false){
      formData=FormData.fromMap(data);
      //files
      if((data!=null)&&(data is Map)){
        List<MultipartFile>  multipartFiles = data['files']??[];
        multipartFiles.forEach((element) async{
          formData.files.add(MapEntry("files",element));
        });
      }

    }
    LogUtil.d('_request-->url=$url');
    var response = await _dio?.request(
        url,
        data: (isFormData??false)?formData:(data),
        queryParameters:queryParameters,
        options: _checkOptions(method,data, options,isAuth:isAuth,contentType: contentType), cancelToken: cancelToken
    );

    dynamic _code;
    String _msg;
    T _data;
    // print("数据返回格式统  response-->$response");
    try {

      Map<String, dynamic> _map = json.decode(response?.data?.toString()??'{}');

      LogUtil.d("数据返回格式统  request一-->$_map");
      _code = _map["code"];
      _msg = _map["message"];
      if(_code== ApiConfig.SUCCESS_CODE){
        if (_map.containsKey("result")){
          if(_map["result"] is String){
            _data=_map["result"];
          }else {
            if (_map["result"]==null) {
              _data=null;
            }
            else {
              if (_map["result"] is Map) {
                _data = generateOBJ(_map["result"]);
              } else if (_map["result"] is List) {
                _data = generateOBJ(_map["result"][0]);
              }
            }
          }
        }
      }

    }catch(e){
      LogUtil.d(e);
      return BaseEntity(ExceptionHandle.parse_error, "数据解析错误", null);
    }
    return BaseEntity(
      _code, _msg, _data,
    );
  }

  Future<BaseEntity<List<T>>> _requestList<T>(String method, String url, {
    bool isFormData:false,
    dynamic data, Map<String, dynamic> queryParameters,CancelToken cancelToken,
    Options options,Function generateOBJ,bool isAuth:false,String contentType}) async {
    LogUtil.d("请求的参数 1-->method=${method},queryParameters=${queryParameters}");
    var response = await _dio?.request(url,
        data: (isFormData??false)?FormData.fromMap(data):(data),
        queryParameters: queryParameters, options: _checkOptions(method,data, options,isAuth: isAuth,contentType: contentType), cancelToken: cancelToken);
    // print("返回的数据 -->data=${response.data}");
    dynamic _code;
    dynamic _msg;
    List<T> _data = [];
    try {
      Map<String, dynamic> _map = json.decode(response?.data?.toString()??'{}');
      LogUtil.d("请求的接口 2-->_map=${response?.data}");
      // var results = _map['results'];
      // if(results==null||(!(results is List)))return BaseEntity(ExceptionHandle.parse_error, "数据解析错误", null);
      // var baseEntity = results[0];
      // if(baseEntity==null||(!(baseEntity is Map)))return BaseEntity(ExceptionHandle.parse_error, "数据解析错误", null);
      _code = _map["code"];
      _msg = _map["message"];
      if(_code== ApiConfig.SUCCESS_CODE){
        if (_map.containsKey("result")){
          ///  List类型处理，暂不考虑Map
          (_map["result"] as List).forEach((item){
//          print('_requestList-->item is Map=${item is Map}');
            var generateOBJData = generateOBJ(item);
            _data.add(generateOBJData);
          });
//        print('_requestList-->_data,length=${_data.length}');
//        BaseEntity(_code, _msg, _data);
        }
      }

    }catch(e){
      LogUtil.d(e);
      return BaseEntity(ExceptionHandle.parse_error, "数据解析错误", null);
    }
    return BaseEntity(_code, _msg, _data,);
  }

  Future<BaseEntity<T>> request<T>(String method, String url, {
    bool isFormData:false,
    dynamic params,Map<String, dynamic> queryParameters, CancelToken cancelToken,String contentType,
    Options options,Function generateOBJ,bool isAuth:false,}) async {

    var response = await _request<T>(method, url,isFormData:isFormData,
        data: params,queryParameters: queryParameters, options: options,
        cancelToken: cancelToken,generateOBJ: generateOBJ,isAuth: isAuth,contentType: contentType);
    return response;
  }

  Future<BaseEntity<List<T>>> requestList<T>(String method, String url, {
    bool isFormData:false,
    dynamic params,Map<String, dynamic> queryParameters,
    CancelToken cancelToken, Options options,Function generateOBJ,bool isAuth:false,String contentType,}) async {
    var response = await _requestList<T>(method, url,isFormData:isFormData, data: params,queryParameters: queryParameters, options: options,
        cancelToken: cancelToken,generateOBJ: generateOBJ,isAuth: isAuth,contentType: contentType);
    return response;
  }

  /// 统一处理(onSuccess返回T对象，onSuccessList返回List<T>)
  Future<BaseEntity> requestNetwork<T>(String method, String url, {
    bool isList:false,
    bool isFormData:false,
    bool isAuth:false ,String contentType,
    dynamic params,Map<String, dynamic> queryParameters, CancelToken cancelToken, Options options,Function generateOBJ})async{
    if(isList==null)isList=false;
    if(isFormData==null)isFormData=false;
    if(queryParameters==null)queryParameters={};
    LogUtil.d("listen： method=$method,url=$url,isList=$isList,isFormData=$isFormData,queryParameters=$queryParameters,options=$options");
    LogUtil.d("listen： params: ${params?.toString()}");
    try{
      var result= await ((!isList) ? request<T>(method, url,isFormData:isFormData,
          params: params,queryParameters: queryParameters, options: options, cancelToken: cancelToken,generateOBJ: generateOBJ,
        isAuth: isAuth,contentType: contentType) :
      requestList<T>(method, url,isFormData:isFormData, params: params, queryParameters:queryParameters,options: options,
        cancelToken: cancelToken,generateOBJ: generateOBJ,
        isAuth:isAuth,contentType: contentType
      ));
      if((result.code??0)==401){
        //登录异常，直接退出登录
        // SpUtils.clear();
        // var instance = await JpushUtils.getInstance();
        // instance.stop();
        // NavigatorUtils.push(navigatorKey.currentContext, BaseRouter.loginPage,clearStack: true);
        return BaseEntity(
          result.code, result.message,result.result,
        );
      }else{
        LogUtil.d("请求的接口 0-->code=${result.code},msg=${result.message}");
        return BaseEntity(
          result.code, result.message,result.result,
        );
      }
    }catch(e){
      // print("请求的接口 0-->e=${e.toString()}");
      Error error = ExceptionHandle.handleException(e);
      return BaseEntity(error.status, error.message,null);
    }
  }

  /***********************************************/
  /*
   * 下载文件
   */
  downloadFile(urlPath, savePath,{Function(int count, int total) onProgress,
    Function() onSuccess,Function(Exception e) onFail,Map<String, dynamic> params,}) async {
    Response response;
    var options = BaseOptions(
      connectTimeout: Duration(milliseconds: 15000),
      receiveTimeout: Duration(milliseconds: 15000),
      responseType: ResponseType.plain,
      validateStatus: (status){
        // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
        return true;
      },
//      baseUrl: Constant.BASE_URL,
//      contentType: ContentType('application', 'x-www-form-urlencoded', charset: 'utf-8'),
    );
    Dio _dio2 = Dio(options);
    /// 统一添加身份验证请求头
//    _dio2.interceptors.add(AuthInterceptor());
//    /// 刷新Token
//    _dio2.interceptors.add(TokenInterceptor());
//    /// 打印Log
//    _dio2.interceptors.add(LoggingInterceptor());
//    /// 适配数据
//    _dio2.interceptors.add(AdapterInterceptor());
    try {
      response = await _dio2.download(urlPath, savePath,data: params,onReceiveProgress: (int count, int total){
        //进度
        LogUtil.d("下载文件进度-->$count $total");
        if(onProgress!=null)onProgress(count,total);
      });
      if(onSuccess!=null)onSuccess();
      print('downloadFile success---------${response.data}');
    } on DioError catch (e) {
      print('downloadFile error---------$e');
//      formatError(e);
      if(onFail!=null)onFail(e);
    }
//    return response.data;
  }
  // 上传文件
  static Future<Response> uploadFile(String path ,{FormData data}) async{
    var options = BaseOptions(
      connectTimeout: Duration(milliseconds: 15000),
      receiveTimeout: Duration(milliseconds: 15000),
      responseType: ResponseType.plain,
      validateStatus: (status){
        // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
        return true;
      },
//      baseUrl: Constant.BASE_URL,
//      contentType: ContentType('application', 'x-www-form-urlencoded', charset: 'utf-8'),
    );
    Dio _dioUp = Dio(options);
    Response response = await _dioUp.post(path,data: data);
    print('uploadFile-->response=${response.toString()}');
    return response;
  }

}
